<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    
</body>
</html>
<script>
    // for...of...
    // for...of...循环可以自动遍历Generator函数运行时生成的Iterator对象 且此时不再需要调用next方法

    function* foo() {
        yield 1;
        yield 2;
        yield 3;
        yield 4;
        yield 5;
        return 6;
    }

    for (let v of foo()) {
        console.log(v);
    }
    // 1 2 3 4 5


    // 上面的代码使用for...of...循环 依次显示5个yield表达式的值
    // 一旦next方法的返回对象done属性为true for...of...循环就会终止 且不包含该返回对象
    // 所以上面代码return语句返回的6 不包括在for...of...循环中


    // 利用for...of...循环 可以写出遍历任意对象的方法
    // 原生JavaScript对象没有遍历接口 无法使用for...of...循环 通过Generator函数为它加上这个接口 就可以用了
    function* objectEntries(obj) {
        let propKeys = Reflect.ownKeys(obj);

        for (let propKey of propKeys) {
            yield [propKey, obj[propKey]];
        }
    }

    let jane = { first: 'Jane', last: 'Doe' };

    for (let [key, value] of objectEntries(jane)) {
        console.log(`${key}: ${value}`);
    }
    // first: Jane
    // last: Doe

    // 上面代码中 对象jane原生不具备 Iterator 接口 无法用for...of遍历
    // 这时 我们通过 Generator 函数objectEntries为它加上遍历器接口 就可以用for...of遍历了
    // 加上遍历器接口的另一种写法是 将 Generator 函数加到对象的Symbol.iterator属性上面

    function* objectEntries() {
        let propKeys = Object.keys(this);

        for (let propKey of propKeys) {
            yield [propKey, this[propKey]];
        }
    }

    let jane = { first: 'Jane', last: 'Doe' };

    jane[Symbol.iterator] = objectEntries;

    for (let [key, value] of jane) {
        console.log(`${key}: ${value}`);
    }
    // first: Jane
    // last: Doe



    // 除了for...of...循环以外 扩展运算符(...)解构赋值 和 Array.from方法内部调用的都是遍历器接口
    // 意味着 它们都可以将Generator函数返回的Iterator对象 作为参数

    function* numbers () {
        yield 1
        yield 2
        return 3
        yield 4
    }

    // 扩展运算符
    [...numbers()] // [1, 2]

    // Array.from 方法
    Array.from(numbers()) // [1, 2]

    // 解构赋值
    let [x, y] = numbers();
    x // 1
    y // 2

    // for...of 循环
    for (let n of numbers()) {
        console.log(n)
    }
    // 1
    // 2


    


</script>